package com.ruoyi.hikvision.task;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.tool.TextUtils;
import com.ruoyi.common.utils.tool.TimerUtils;
import com.ruoyi.hikvision.hk.HikvisionClient;
import com.ruoyi.hikvision.hk.HikvisionService;
import com.ruoyi.wisdom.constants.IotConstants;
import com.ruoyi.wisdom.domain.IotPickDevice;
import com.ruoyi.wisdom.domain.IotPickDeviceFace;
import com.ruoyi.wisdom.domain.IotPickFace;
import com.ruoyi.wisdom.service.IIotPickDeviceFaceService;
import com.ruoyi.wisdom.service.IIotPickDeviceService;
import com.ruoyi.wisdom.service.IIotPickFaceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class HikvisionTask {

    @Autowired
    private IotConstants iotConstants;

    @Autowired
    private IIotPickFaceService iotPickFaceService;

    @Autowired
    private IIotPickDeviceService iotPickDeviceService;

    @Autowired
    private IIotPickDeviceFaceService pickDeviceFaceService;

    private Map<String, IotPickDevice> deviceMap;

    private Long startAmTime = null;//开始时间[上午]
    private Long startPmTime = null;//开始时间[下午]
    private final long stepTime = 10 * 60 * 1000;//读取设备本地记录间隔：10分钟

    public IotPickDevice getDevice(String deviceNo) {
        if (deviceMap == null) {
            deviceMap = new HashMap<>();
            IotPickDevice params = new IotPickDevice();
            params.setDeviceType(IotConstants.DEVICE_TYPE_FACEGATE);
            params.setDeviceFactory(IotConstants.DEVICE_FACTORY_HK);
            List<IotPickDevice> deviceList = iotPickDeviceService.selectIotPickDeviceList(params);
            for (IotPickDevice pickDevice : deviceList) {
                deviceMap.put(pickDevice.getDeviceNo(), pickDevice);
            }
        }else {
            boolean hasDevice = deviceMap.containsKey(deviceNo);
            if (!hasDevice) {
                IotPickDevice params = new IotPickDevice();
                params.setDeviceType(IotConstants.DEVICE_TYPE_FACEGATE);
                params.setDeviceFactory(IotConstants.DEVICE_FACTORY_HK);
                List<IotPickDevice> deviceList = iotPickDeviceService.selectIotPickDeviceList(params);
                for (IotPickDevice pickDevice : deviceList) {
                    deviceMap.put(pickDevice.getDeviceNo(), pickDevice);
                }
            }
        }

        return deviceMap.getOrDefault(deviceNo, null);
    }

    /**
     * 设备检测
     */
    //@Scheduled(fixedDelay = 10 * 1000, initialDelay = 10 * 1000)
    @Scheduled(fixedRate = 10000) // 每10秒执行一次
    public void deviceCheck() {
        HikvisionService hikvisionService = HikvisionService.getInstance();
        List<String> deviceNos = hikvisionService.checkDevice();
        if (deviceNos.size() > 0) {
            // 更新设备在线状态
            String onlineTime = TimerUtils.getDateTime();
            IotPickDevice iotPickDevice = new IotPickDevice();
            iotPickDevice.setInDeviceNos(deviceNos);
            iotPickDevice.setDeviceFactory(IotConstants.DEVICE_FACTORY_HK);
            iotPickDevice.setOnline(IotConstants.DEVICE_STATUS_ONLINE);
            iotPickDevice.setOnlineTime(onlineTime);
            iotPickDeviceService.updateIotPickDeviceOnline(iotPickDevice);

            // 更新掉线的设备
            IotPickDevice iotPickDevice2 = new IotPickDevice();
            iotPickDevice2.setNoInDeviceNos(deviceNos);
            iotPickDevice2.setDeviceFactory(IotConstants.DEVICE_FACTORY_HK);
            iotPickDevice2.setOnline(IotConstants.DEVICE_STATUS_OUTLINE);
            iotPickDeviceService.updateIotPickDeviceOnline(iotPickDevice2);

            // 更加设备去下发人脸
            for (String deviceNo : deviceNos) {
                checkAddPickDeviceFace(deviceNo);
                checkDelPickDeviceFace(deviceNo);
            }
        } else {
            // 更新为都掉线
            IotPickDevice iotPickDevice3 = new IotPickDevice();
            iotPickDevice3.setOnline(IotConstants.DEVICE_STATUS_OUTLINE);
            iotPickDevice3.setDeviceFactory(IotConstants.DEVICE_FACTORY_HK);
            iotPickDeviceService.updateIotPickDeviceOnline(iotPickDevice3);
        }
    }

    /**
     * 下发人脸
     */
    //@Scheduled(fixedDelay = 5 * 1000, initialDelay = 5 * 1000)
    @Scheduled(fixedRate = 10000) // 每10秒执行一次
    public void downloadPickFace() {
        System.out.println("下发人脸");
        IotPickFace faceParams = new IotPickFace();
        faceParams.setStatus(IotConstants.FACE_STATUS_ADD);
        faceParams.setStatusOld(IotConstants.FACE_STATIC_OLD_ADD);
        List<IotPickFace> faceList = iotPickFaceService.selectIotPickFaceList(faceParams);

        if (faceList == null || faceList.size() == 0) return;
        HikvisionService hikvisionService = HikvisionService.getInstance();
        System.out.println("下发人脸开始：" + TimerUtils.getDateTime());
        for (IotPickFace pickFace : faceList) {
            String downloadDevice = pickFace.getDownloadDevice();
            if (StringUtils.isEmpty(downloadDevice)) continue;
            String[] devices = downloadDevice.split(",");
            List<String> successDevices = new ArrayList<>();
            List<String> failDevices = new ArrayList<>();

            for (String deviceNo : devices) {
                System.out.println("人脸下发设备：" + deviceNo);
                IotPickDevice pickDevice = getDevice(deviceNo);
                if (pickDevice == null) {
                    failDevices.add(deviceNo);
                    continue;
                }
                HikvisionClient deviceClient = hikvisionService.getDevice(pickDevice.getIp());
                if (deviceClient == null){
                    failDevices.add(deviceNo);
                    continue;
                }
                // 设置HikvisionClient
                setHikviisonClient(deviceClient);

                System.out.println("设备状态:" + deviceClient + " 设备IP：" + pickDevice.getIp());
                if (deviceClient == null) {
                    failDevices.add(deviceNo);
                    continue;
                }
                Boolean addUserStatus = deviceClient.addUserInfo(pickFace.getFacecode(), pickFace.getName(), pickFace.getSex());
                if (addUserStatus) {
                    Boolean addFaceStatus = deviceClient.addFaceInfo(pickFace.getFacecode(), pickFace.getFace());
                    if (addFaceStatus) {
                        successDevices.add(deviceNo);
                    } else {
                        failDevices.add(deviceNo);
                    }
                } else {
                    failDevices.add(deviceNo);
                }
            }

            // 保存数据
            if (failDevices.size() > 0) {
                String failDevice = String.join(",", failDevices);
                pickFace.setFailDevice(failDevice);

                // 更新设备人脸
                IotPickDeviceFace updateDeviceFace = new IotPickDeviceFace();
                updateDeviceFace.setFacecode(pickFace.getFacecode());
                updateDeviceFace.setInDeviceNos(failDevices);
                updateDeviceFace.setStatus(IotConstants.FACE_STATUS_ADD_FAIL);
                pickDeviceFaceService.updateIotPickDeviceFaceByParams(updateDeviceFace);
            }
            if (successDevices.size() > 0) {
                String successDevice = String.join(",", successDevices);
                pickFace.setSuccessDevice(successDevice);
                pickFace.setDownloadNum(successDevices.size());

                // 更新设备人脸
                IotPickDeviceFace updateDeviceFace = new IotPickDeviceFace();
                updateDeviceFace.setFacecode(pickFace.getFacecode());
                updateDeviceFace.setInDeviceNos(successDevices);
                updateDeviceFace.setStatus(IotConstants.FACE_STATUS_ADD_SUCCESS);
                pickDeviceFaceService.updateIotPickDeviceFaceByParams(updateDeviceFace);
            }
            if (successDevices.size() == 0) {
                // 下发失败
                pickFace.setStatus(IotConstants.FACE_STATUS_ADD_FAIL);
            } else if (successDevices.size() == devices.length) {
                // 下发成功
                pickFace.setStatus(IotConstants.FACE_STATUS_ADD_SUCCESS);
            } else {
                // 部分下发成功
                pickFace.setStatus(IotConstants.FACE_STATUS_TO_DOING);
            }
            iotPickFaceService.updateIotPickFace(pickFace);
        }
        System.out.println("下发人脸结束：" + TimerUtils.getDateTime());
    }

    /**
     * 删除人脸
     */
    //@Scheduled(fixedDelay = 10 * 1000, initialDelay = 10 * 1000)
    @Scheduled(fixedRate = 5000) // 每10秒执行一次
    public void deletePickFace() {
        IotPickFace faceParams = new IotPickFace();
        faceParams.setStatus(IotConstants.FACE_STATUS_DELETE);
        faceParams.setStatusOld(IotConstants.FACE_STATIC_OLD_DEL);
        List<IotPickFace> faceList = iotPickFaceService.selectIotPickFaceList(faceParams);
        if (faceList == null || faceList.size() == 0) return;
        HikvisionService hikvisionService = HikvisionService.getInstance();
        System.out.println("删除人脸开始：" + TimerUtils.getDateTime());
        for (IotPickFace pickFace : faceList) {
            String downloadDevice = pickFace.getDownloadDevice();
            if (StringUtils.isEmpty(downloadDevice)) continue;
            String[] devices = downloadDevice.split(",");
            List<String> deleteDevices = new ArrayList<>();

            for (String deviceNo : devices) {
                IotPickDevice pickDevice = getDevice(deviceNo);
                if (pickDevice == null) continue;
                HikvisionClient deviceClient = hikvisionService.getDevice(pickDevice.getIp());
                if (deviceClient == null){
                    continue;
                }
                // 设置HikvisionClient
                setHikviisonClient(deviceClient);

                if (deviceClient == null) continue;
                Boolean delResult = deviceClient.deleteUserInfo(pickFace.getFacecode());
                if (delResult) {
                    deleteDevices.add(deviceNo);
                }
            }

            // 保存数据
            if (deleteDevices.size() == 0) {
                pickFace.setStatus(IotConstants.FACE_STATUS_DELETE_FAIL);
            } else {
                if (deleteDevices.size() == devices.length) {
                    pickFace.setStatus(IotConstants.FACE_STATUS_DELETE_SUCCESS);
                } else {
                    pickFace.setStatus(IotConstants.FACE_STATUS_TO_DOING);
                }
                String successDevice = String.join(",", deleteDevices);
                pickFace.setDeleteDevice(successDevice);
                pickFace.setDeleteNum(deleteDevices.size());
            }
            iotPickFaceService.updateIotPickFace(pickFace);
        }
        System.out.println("删除人脸结束：" + TimerUtils.getDateTime());
    }

    /**
     * 检测设备的人脸添加
     */
    public void checkAddPickDeviceFace(String deviceNo) {
        IotPickDeviceFace addParams = new IotPickDeviceFace();
        addParams.setDeviceNo(deviceNo);
        addParams.setStatus(IotConstants.FACE_STATUS_ADD);
        addParams.setStatusOld(IotConstants.FACE_STATIC_OLD_ADD);
        List<IotPickDeviceFace> addfaceList = pickDeviceFaceService.selectIotPickDeviceFaceList(addParams);
        if (addfaceList.size() > 0) {
            IotPickDevice pickDevice = getDevice(deviceNo);
            if (pickDevice != null) {
                HikvisionService hikvisionService = HikvisionService.getInstance();
                HikvisionClient deviceClient = hikvisionService.getDevice(pickDevice.getIp());
                if (deviceClient == null) return;
                // 设置HikvisionClient
                setHikviisonClient(deviceClient);

                System.out.println("设备状态:" + deviceClient + " 设备IP：" + pickDevice.getIp());
                if (deviceClient != null) {
                    for (IotPickDeviceFace pickFace : addfaceList) {

                        Integer statusResult = IotConstants.FACE_STATUS_ADD_FAIL;
                        Boolean addUserStatus = deviceClient.addUserInfo(pickFace.getFacecode(), pickFace.getName(), pickFace.getSex());
                        if (addUserStatus) {
                            Boolean addFaceStatus = deviceClient.addFaceInfo(pickFace.getFacecode(), pickFace.getFace());
                            if (addFaceStatus) {
                                // 成功
                                statusResult = IotConstants.FACE_STATUS_ADD_SUCCESS;
                                ;
                            }
                        }

                        // 更新结果集
                        // 1、iot_pick_device_face
                        pickFace.setStatus(statusResult);
                        pickDeviceFaceService.updateIotPickDeviceFace(pickFace);

                        // 2、iot_pick_device
                        IotPickFace iotPickFace = iotPickFaceService.selectIotPickFaceByFaceCode(pickFace.getFacecode());
                        if (iotPickFace != null) {

                            String[] downloadDevices = iotPickFace.getDownloadDevice().split(",");
                            if (statusResult == IotConstants.FACE_STATUS_ADD_SUCCESS) {
                                // 下发成功更新 success_device、status
                                String successDevice = TextUtils.addUniqueString(iotPickFace.getSuccessDevice(), deviceNo);
                                String[] successDevices = successDevice.split(",");
                                if (successDevices.length == downloadDevices.length) {
                                    iotPickFace.setStatus(IotConstants.FACE_STATUS_ADD_SUCCESS);
                                } else {
                                    iotPickFace.setStatus(IotConstants.FACE_STATUS_TO_DOING);
                                }
                                iotPickFace.setSuccessDevice(successDevice);
                                iotPickFace.setDownloadNum(successDevices.length);
                            } else {
                                // 下发失败
                                String failDevice = TextUtils.addUniqueString(iotPickFace.getFailDevice(), deviceNo);
                                String[] failDevices = failDevice.split(",");
                                if (failDevices.length == downloadDevices.length) {
                                    iotPickFace.setStatus(IotConstants.FACE_STATUS_ADD_FAIL);
                                } else {
                                    iotPickFace.setStatus(IotConstants.FACE_STATUS_TO_DOING);
                                }
                                iotPickFace.setFailDevice(failDevice);
                            }
                            iotPickFaceService.updateIotPickFace(iotPickFace);
                        }
                    }
                }
            }
        }
    }

    /**
     * 检测设备人脸删除
     *
     * @param deviceNo
     */
    public void checkDelPickDeviceFace(String deviceNo) {
        IotPickDeviceFace delParams = new IotPickDeviceFace();
        delParams.setDeviceNo(deviceNo);
        delParams.setStatus(IotConstants.FACE_STATUS_DELETE);
        delParams.setStatusOld(IotConstants.FACE_STATIC_OLD_DEL);
        List<IotPickDeviceFace> delfaceList = pickDeviceFaceService.selectIotPickDeviceFaceList(delParams);
        if (delfaceList.size() > 0) {
            IotPickDevice pickDevice = getDevice(deviceNo);
            if (pickDevice != null) {
                HikvisionService hikvisionService = HikvisionService.getInstance();
                HikvisionClient deviceClient = hikvisionService.getDevice(pickDevice.getIp());
                if (deviceClient == null) return;
                // 设置HikvisionClient
                setHikviisonClient(deviceClient);

                System.out.println("设备状态:" + deviceClient + " 设备IP：" + pickDevice.getIp());
                if (deviceClient != null) {
                    for (IotPickDeviceFace pickFace : delfaceList) {
                        // 删除人员
                        Boolean delResult = deviceClient.deleteUserInfo(pickFace.getFacecode());
                        if (delResult) {
                            // 1、iot_pick_device_face
                            pickFace.setStatus(IotConstants.FACE_STATUS_DELETE_SUCCESS);
                            pickDeviceFaceService.updateIotPickDeviceFace(pickFace);

                            // 2、iot_pick_face
                            IotPickFace iotPickFace = iotPickFaceService.selectIotPickFaceByFaceCode(pickFace.getFacecode());
                            if (iotPickFace != null) {
                                String deleteDevice = TextUtils.addUniqueString(iotPickFace.getDeleteDevice(), deviceNo);
                                if (iotPickFace.getStatusOld() == IotConstants.FACE_STATIC_OLD_DEL) {
                                    // 删除 操作
                                    String[] deleteDevices = deleteDevice.split(",");
                                    String[] downloadDevices = iotPickFace.getDownloadDevice().split(",");
                                    if (deleteDevices.length >= downloadDevices.length) {
                                        iotPickFace.setStatus(IotConstants.FACE_STATUS_DELETE_SUCCESS);
                                    } else {
                                        iotPickFace.setStatus(IotConstants.FACE_STATUS_TO_DOING);
                                    }
                                }
                                iotPickFace.setDeleteDevice(deleteDevice);
                                iotPickFaceService.updateIotPickFace(iotPickFace);
                            }
                        }
                    }
                }
            }
        }
    }

    private Long getAmTime() {
        String aTime = TimerUtils.getDateTime("yyyy-MM-dd") + " 00:00:00";
        return TimerUtils.dateFormatToTime(aTime, "yyyy-MM-dd HH:mm:ss");
    }

    private Long getPmTime() {
        String aTime = TimerUtils.getDateTime("yyyy-MM-dd") + " 12:00:00";
        return TimerUtils.dateFormatToTime(aTime, "yyyy-MM-dd HH:mm:ss");
    }

    @Scheduled(fixedDelay = 10 * 1000, initialDelay = 15 * 1000)
    public void pushLocalRecord1() {
        if (startAmTime == null || startAmTime > getPmTime()) {
            startAmTime = getAmTime();
        }
        pushLocalRecord(startAmTime);
        startAmTime += stepTime;
    }

    @Scheduled(fixedDelay = 10 * 1000, initialDelay = 20 * 1000)
    public void pushLocalRecord2() {
        if (startPmTime == null || startPmTime > System.currentTimeMillis()) {
            startPmTime = getPmTime();
        }
        pushLocalRecord(startPmTime);
        startPmTime += stepTime;
    }

    private void pushLocalRecord(Long startTime) {
        if (startTime == null || startTime > System.currentTimeMillis()) return;
        HikvisionService hikvisionService = HikvisionService.getInstance();
        hikvisionService.getClientMap().forEach((key, client) -> {
            client.searchEvent(5, 75, TimerUtils.timeToDateTime(startTime), TimerUtils.timeToDateTime(startTime + stepTime));
        });
    }

    /**
     * 设置 HikvisionClient
     *
     * @param deviceClient
     */
    private void setHikviisonClient(HikvisionClient deviceClient) {
        if (deviceClient != null){
            System.out.println("设置 HikvisionClient："+iotConstants.getIotConfig());
            System.out.println(deviceClient);
            System.out.println(iotConstants.getIotConfig().getLocalFaceUrl());
            deviceClient.setLocalFaceUrl(iotConstants.getIotConfig().getLocalFaceUrl());
        }
    }
}
